Найдите наибольшую общую
подпоследовательность двух строк.
Вход. Две
строки, состоящие только из маленьких букв английского алфавита. Длина каждой
строки не превышает 1000 символов.
Выход. Выведите наибольшую общую
подпоследовательность двух строк.
|
Пример
входа |
Пример
выхода |
|
abacaba dacabc |
acab |
наибольшая
общая подпоследовательность
В задаче следует
найти наибольшую общую подпоследовательность (НОП) двух строк и вывести ее.
Построим массив dp, где dp[i][j] равно длине НОП
строк x[1…i] и y[1…j]. Значение dp[n][m] будет равно
длине НОП исходных строк (|x| = n, |y|
= m).
После вычисления массива dp
восстановим НОП, совершив обратный проход по матрице dp от ячейки (n, m) до (0, 0). Для текущей позиции (i, j) выполняем следующие шаги:
·
если символы xi и yj совпадают, этот символ должен быть включён в НОП. Добавляем его в
результирующую строку res и переходим к ячейке (i – 1, j – 1), то есть продолжаем строить
НОП для строк x[1…i – 1] и y[1…j – 1].
·
если символы xi и yj различны, то переходим к ячейке (i, j – 1) или (i – 1, j), выбирая ту, где значение
больше. Если значения в ячейках dp[i – 1][j] и dp[i][j – 1] равны, переход возможен в
любую из них.
Результирующая строка res будет содержать наибольшую
общую подпоследовательность строк x и y.
Пример
Рассмотрим процесс
нахождения наибольшей общей подпоследовательности (НОП) для двух строк,
приведённых в примере.

Поиск общей подпоследовательности
начинается с позиции (i, j) = (6, 7).
y[6] ≠ x[7]: переходим в любую соседнюю
ячейку с максимальным значением, например, в (5, 7).
y[5] ≠ x[7]: двигаемся в (5, 6).
y[5] = x[6] = ‘b’: совершаем переход по диагонали и включаем букву ‘b’ в НОП.
Объявим входные строки x и y. Для нахождения
их НОП используем массив dp.
#define MAX 1001
int dp[MAX][MAX];
string x, y, res;
Читаем входные строки и добавляем к ним пробел спереди, чтобы индексация
начиналась с 1.
cin >> x; n =
x.length(); x = " " + x;
cin >> y; m =
y.length(); y = " " + y;
Находим НОП.
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
if (x[i] == y[j])
dp[i][j]
= dp[i - 1][j - 1] + 1;
else
dp[i][j]
= max(dp[i - 1][j], dp[i][j - 1]);
В строке res строим НОП.
i = n; j = m;
while (i >= 1 && j >= 1)
if (x[i] == y[j])
{
res = res + x[i];
i--;
j--;
}
else
{
if
(dp[i - 1][j] > dp[i][j - 1])
i--;
else
j--;
}
Обращаем и выводим результирующую строку.
reverse(res.begin(), res.end());
cout << res << endl;